<?php
/**
 * Created by PhpStorm.
 * User: jacob
 * Date: 18-7-26
 * Time: 下午5:41
 */
namespace DB;

use Config\Time;
use MongoDB\BSON\ObjectID;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Command;
use MongoDB\Driver\Exception\BulkWriteException;
use MongoDB\Driver\Manager;

class ArticleInfo{
  public $_id;
  public $title;
  public $author;
  public $description;
  public $content;
  public $create_time;
  public $update_time;
  public $view_count;

  public function toArray(){
    $array = json_decode(json_encode($this),true);
    return array_filter($array,function ($k,$v){
      return $k !== null;
    },ARRAY_FILTER_USE_BOTH);
  }
}

class Article extends Mongodb {
  const id = "_id";
  const title = "title";
  const author = "author";
  const description = "description";
  const content = "content";
  const create_time = "create_time";
  const update_time = "update_time";
  const view_count = "view_count";
  private $id;

  public function __construct(string $id = "") {
    $this->id = $id;
    parent::__construct("articles");
  }

  public function getInfo(ArticleInfo $info):int {
    $filter = [self::id => $info->_id];
    $cursor = $this->getMany($filter)->toArray();
    if (count($cursor) == 0){
      return 0;
    }
    foreach ($cursor[0] as $key => $value){
      $info->{$key} = $value;
    }
    return 1;
  }

  public function insert(ArticleInfo $info):bool {
    $bulkwrite = new BulkWrite();
    if (empty($info->_id)){
      $info->_id = new ObjectID()."";
    }
    if (empty($info->create_time)){
      $info->create_time = Time::millisecond();
    }
    $values = $info->toArray();
    $bulkwrite->insert($values);
    $manager = $this->getManager();
    return $this->bulkWrite($manager,$bulkwrite);
  }

  public function update(ArticleInfo $info):bool {
    $bulkwrite = new BulkWrite();
    $info->update_time = Time::millisecond();
    $filter = [self::id => $info->_id];
    $newObj = ['$set' => [self::title => $info->title,
      self::content => $info->content,self::update_time => $info->update_time]];
    $options = ["multi" => false,"upsert" => false];
    $bulkwrite->update($filter,$newObj,$options);
    $manager = $this->getManager();
    return $this->bulkWrite($manager,$bulkwrite);
  }

  public function delete(ArticleInfo $info):bool {
    $bulkwrite = new BulkWrite();
    $filter = [self::id => $info->_id];
    $options = ["limit" => 1]; //limit:0删除所有匹配数据，limit:1删除第一条匹配数据
    $bulkwrite->delete($filter,$options);
    $manager = $this->getManager();
    return $this->bulkWrite($manager,$bulkwrite);
  }

  /**
   * 创建索引
   */
  public function createIndex(){
    $db = new Article();
    $cmd = [];
    $cmd['createIndexes'] = $db->getnamespace();
    $cmd['indexes'] = [
      'key' => [self::create_time => 1],
      'name' => $db->getnamespace() . "_".self::create_time."_1",
      'unique' => false,
      'partialFilterExpression' => [self::create_time => ['$exists' => true]]
    ];
    $manager = $this->getManager();
    try{
      $manager->executeCommand($db->getDbName(),new Command($cmd));
    }catch (\Exception $e){
      echo $e->getCode().".".$e->getMessage();
    }
  }

  public function aggregate(){
    $command = new Command([
      'aggregate' => $this->getColName(),
      'pipeline' => [
        ['$group' => ['_id' => '$title','sum' => ['$sum' => '$likes']]]
      ],
      'cursor' => new \stdClass()
    ]);
    $manager = $this->getManager();
    $cursor = $manager->executeCommand($this->getDbName(),$command);
    $response = $cursor->toArray();
    return $response;
  }

  private function bulkWrite(Manager $manager,BulkWrite $bulkwrite):bool {
    try{
      $manager->executeBulkWrite($this->getNamespace(),$bulkwrite);
      return true;
    }catch (BulkWriteException $e){
      echo $e->getCode().".".$e->getMessage();
      return false;
    }catch (\Exception $e){
      echo $e->getCode().".".$e->getMessage();
      return false;
    }
  }

}